package ar.edu.utn.injectors;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Hashtable;

import ar.edu.utn.exceptions.ReflectionException;

public class SetterPrymitiveInyector {
	private String prefix;

	public SetterPrymitiveInyector() {
		prefix = "set";
	}

	public void inyect(Object componentInstance,
			Hashtable<String, Object> property) throws ReflectionException {
		Method[] methods = componentInstance.getClass().getDeclaredMethods();
		for (Method method : methods) {
			if (isSetterMethod(method)) {
				Object propertyValue = property.get(this
						.getPropertyName(method));

				this.inyectInto(method, componentInstance, propertyValue);
			}

		}

	}

	protected void inyectInto(Method method, Object componentInstance,
		Object propertyValue) throws ReflectionException {
		try{
			method.invoke(componentInstance, propertyValue);
		}catch(IllegalArgumentException e1){
			throw new ReflectionException("Se produjo un error con los argumentos del metodo a invocar", e1.getCause());
		}catch (IllegalAccessException e2) {
			throw new ReflectionException(e2.getMessage(), e2.getCause());
		}catch (InvocationTargetException e3) {
			throw new ReflectionException("Se produjo un error en la invocacion del metodo", e3.getCause());
		}
	}

	public boolean isSetterMethod(Method method) {
		String name = method.getName();
		return name.startsWith(prefix) && name.length() > 3
				&& method.getGenericParameterTypes().length == 1;
	}

	private String getPropertyName(Method method) {
		final String name = method.getName();
		String result = name.substring(3);
		
		if (result.length() > 1 && !Character.isUpperCase(result.charAt(1))) {
			result = "" + Character.toLowerCase(result.charAt(0))
					+ result.substring(1);
		} else if (result.length() == 1) {
			result = result.toLowerCase();
		}
		return result;

	}

}
